package com.only.common.util;

import cn.hutool.core.util.StrUtil;

import java.util.*;

/**
 * @author xuxx
 * @date 2024-01-22 11:18
 */
public class StringReplaceUtil {
    /**
     * 提取所有模块名字
     * @return 元素的格式： [program:xxxxx]
     */
    public static List<String> extractAllModuleName(List<String> content) {
        List<String> modules = new ArrayList<>();

        for (String line : content) {
            String fixedLine = line.trim();
            if (fixedLine.startsWith("[")) {
                modules.add(purificationLine(fixedLine));
            }
        }

        return modules;
    }

    /**
     * 提取第一个 item 的值
     * @param content
     * @param itemName
     * @return
     */
    public static String extractFirstItemValue(List<String> content, String itemName) {
        return extractFirstItemValue(content, itemName, "=");
    }

    /**
     * 提取第一个 item 的值
     * @param content
     * @param itemName
     * @return
     */
    public static String extractFirstItemValue(List<String> content, String itemName, String splitKey) {
        String key1 = itemName + splitKey;
        String key2 = itemName + " ";
        for (String line : content) {
            String fixedLine = line.trim();
            if (!isVoidLine(fixedLine)) {
                if (fixedLine.startsWith(key1) || fixedLine.startsWith(key2)) {
                    fixedLine = purificationLine(fixedLine);
                    String[] fields = fixedLine.split(splitKey, 2);
                    if (fields.length == 2) {
                        return fields[1];
                    }
                }
            }
        }

        throw new RuntimeException(StrUtil.format("配置文件中不存在配置项：{}", itemName));
    }

    public static Optional<String> extractFirstItemValueWithOption(List<String> content, String itemName, String splitKey) {
        try {
            return Optional.ofNullable(extractFirstItemValue(content, itemName, splitKey));
        } catch (Exception ex) {
            return Optional.empty();
        }
    }

    public static Optional<String> extractItemValueWithOption(List<String> content, String moduleName, String itemName) {
        try {
            return Optional.ofNullable(extractItemValue(content, moduleName, itemName));
        } catch (Exception ex) {
            return Optional.empty();
        }
    }

    /**
     * 找到指定模块下的配置项的值
     * @param content 配置文件的内容
     * @param moduleName 配置模块
     * @param itemName 配置项
     */
    public static String extractItemValue(List<String> content, String moduleName, String itemName) {
        String splitKey = "=";
        int moduleStart = content.indexOf(moduleName);
        if (moduleStart == -1) {
            throw new RuntimeException(StrUtil.format("配置文件中，模块：{} 不存在", moduleName));
        }

        int moduleEnd = findNextModuleIndex(content, moduleStart + 1);
        if (moduleEnd == -1) {
            moduleEnd = content.size();
        }

        int itemIndex = findItemIndex(content, moduleStart, moduleEnd, itemName, splitKey);
        if (itemIndex == -1) {
            throw new RuntimeException(StrUtil.format("配置文件中，模块：{} 的配置项：{} 不存在", moduleName, itemName));
        } else {
            String lineContent = content.get(itemIndex);
            lineContent = purificationLine(lineContent); // 需要去除注释相关的信息
            String[] fields = lineContent.split(splitKey, 2);
            if (fields.length == 2) {
                return fields[1];
            } else {
                return "";
            }
        }
    }

    /**
     * 从模块中提取第一行匹配 prefix 的行，不管是不是注释行
     * 不对原内容进行处理
     * @param content
     * @param moduleName
     * @param prefix 如： #systemId=100 时，prefix 为 #systemId
     * @return
     */
    public static Optional<String> extractLineInModule(List<String> content, String moduleName, String prefix) {
        int moduleStart = content.indexOf(moduleName);
        if (moduleStart == -1) {
            throw new RuntimeException(StrUtil.format("配置文件中，模块：{} 不存在", moduleName));
        }

        int moduleEnd = findNextModuleIndex(content, moduleStart + 1);
        if (moduleEnd == -1) {
            moduleEnd = content.size();
        }

        for (int i = moduleStart; i < moduleEnd; i++) {
            String line = content.get(i);
            if (line.trim().startsWith(prefix)) {
                return Optional.of(line);
            }
        }

        return Optional.empty();
    }

    /**
     * 替换模块中的配置项，如果模块不存在，会自动加入模块
     * 新加入的模块会加到文件尾部，所以加入多个模块时需要按顺序来处理
     * 需要加入的 item 会加到模块的尾部，所以需要按顺序进行处理
     *
     * @param content 模板内容
     * @param moduleName 模块，如：[inet_http_server] 这样的标记定义为一个模块
     * @param itemName 配置项名称，如：port 就是一个配置项（key）
     * @param itemValue 配置项的值，如：port=1.1.1.1:8080, 那么 itemValue 为 1.1.1.1:8080
     */
    public static void replaceOrAddItem(List<String> content, String moduleName, String itemName, String itemValue) {
        int moduleStart = content.indexOf(moduleName);
        if (moduleStart == -1) {
            content.add(""); // 用于模块间换行操作
            content.add(moduleName);
            moduleStart = content.size() - 1;
        }

        int moduleEnd = findNextModuleIndex(content, moduleStart + 1);
        if (moduleEnd == -1) {
            moduleEnd = content.size();
        }

        int itemIndex = findItemIndex(content, moduleStart, moduleEnd, itemName, "=");
        if (itemIndex == -1) {
            // 未找到需要替换的行，在模块的尾部加入
            content.add(moduleEnd, StrUtil.format("{}={}", itemName, itemValue));
        } else {
            // 找到需要替换的行了
            content.set(itemIndex, StrUtil.format("{}={}", itemName, itemValue));
        }
    }

    /**
     * 替换或增加指定行
     * @param content
     * @param lineKey
     * @param replaceLine
     */
    public static String replaceLineByKeyValueType(String content, String lineKey, String replaceLine, String splitStr) {
        StringBuilder contentBuilder = new StringBuilder("");
        String[] lines = content.split("\n");
        if (StrUtil.isNotEmpty(lineKey)) {
            lineKey = lineKey.trim();
        }
        boolean hasReplace = false;
        for (String line :lines) {
            String[] lineKeyAndValue = line.split(splitStr);
            if (lineKeyAndValue.length >= 2){
                String key = lineKeyAndValue[0];
                if (StrUtil.isNotEmpty(key)) {
                    key = key.trim();
                }
                if (Objects.equals(key,lineKey)) {
                    hasReplace = true;
                    line = replaceLine;
                }
            }
            contentBuilder.append(line).append("\n");
        }
        // 如果找不到
        if(!hasReplace && contentBuilder.indexOf(replaceLine) == -1){
            contentBuilder.append("\n").append(replaceLine);
        }
        // content 一直变的
        return contentBuilder.toString();
    }

    private static int findNextModuleIndex(List<String> content, int moduleStart) {
        if (moduleStart >= content.size()) {
            return -1;
        }

        for (int i = moduleStart; i < content.size(); i++) {
            String line = content.get(i).trim();
            // 空行和注释行跳过
            if (isVoidLine(line)) {
                continue;
            }

            if (line.startsWith("[")) {
                return i;
            }
        }

        return - 1;
    }

    private static int findItemIndex(List<String> content, int moduleStart, int moduleEnd, String item, String splitKey) {
        for (int i = moduleStart; i < moduleEnd; i++) {
            String line = content.get(i).trim();

            // 空行和注释行跳过
            if (isVoidLine(line)) continue;

            String[] field = line.split(splitKey, 2);
            if (field.length >= 1) {
                if (Objects.equals(field[0], item)) return i;
            }
        }

        return -1;
    }

    /**
     * 将有效行的的内容提纯，将注释的内容去掉
     * @param line
     * @return
     */
    private static String purificationLine(String line) {
        int index = line.indexOf("#");
        if (index == -1) return line;
        else {
            return line.substring(0, index).trim();
        }
    }

    private static boolean isVoidLine(String line) {
        // 空行和注释行跳过
        return StrUtil.isBlank(line) || line.startsWith("#");
    }

    /**
     * 内容转map
     * @param content
     * @param splitStr
     * @return
     */
    public static LinkedHashMap<String,String> contentToMap(String content, String splitStr){
        LinkedHashMap<String,String>  contentMap = new LinkedHashMap<>();
        if (StrUtil.isEmpty(content)){
            return contentMap;
        }
        String[] lines = content.split("\n");

        for (String line: lines) {
            if (StrUtil.isNotEmpty(line)) {
                String[] keyValue = line.split(splitStr);
                String key = keyValue[0];
                String value = null;
                if (keyValue.length > 1) {
                    StringBuilder valueBuilder = new StringBuilder("");
                    for (int i = 1; i < keyValue.length; i++) {
                        valueBuilder.append(keyValue[i]).append(splitStr);
                    }
                    valueBuilder.deleteCharAt(valueBuilder.lastIndexOf(splitStr));
                    value = valueBuilder.toString();
                }
                contentMap.put(key,value);
            }
        }
        return contentMap;
    }

    /**
     * map 转内容
     * @param contentMap
     * @param splitStr
     * @return
     */
    public static String mapToContent(LinkedHashMap<String,String> contentMap, String splitStr) {
        StringBuilder contentBuilder = new StringBuilder("");
        contentMap.forEach((k,v) -> {
            contentBuilder.append(k);
            if (v != null){
                contentBuilder.append(splitStr).append(v);
            }
            contentBuilder.append("\n");
        });
        return contentBuilder.toString();
    }
}
